变量
Unix shell 也有变量. 能对这些变量赋值, 也可以从这些变量取值.
变量的存储
要在 shell 里增加变量, 必须有个地方能存放这些变量的名称和值, 而且 这个变脸的存储系统必须能够分辨局部和全局变量.
struct var { char *str; /* name = var string */ int global; /* a boolean */ }; static struct var tab[MAXVARS];
增加变量命令: built-ins
set 是 shell 的一个命令, 而不是由 shell 运行的程序, 这就像 if 和then 这些关键字由 shell 自己处理一样.
修改 process 函数, 使之调用 fork/exec 之前检查是否为内置命令:
/* process.c * command processing layer * * The process(char **arglist) function is called by the main loop * It sits in front of the execute() function. This layer handles * two main classes of processing: * a) built-in functions (e.g. exit(), set, =, read,..) * b) control structures (e.g. if, while, for) */ #include <stdio.h> #include "smsh.h" int is_control_command(char *); int do_control_command(char **); int ok_to_execute(); int process(char **args) /* * purpose: process user command * returns: result of processing command * details: if a built-in then call appropriate function, if not * execute() * errors: arise form subroutines, handled there */ { int rv = 0; if (args[0] == NULL) rv = 0; else if (is_control_command(args[0])) rv = do_control_command(args); else if (ok_to_execute()){ if (!builtin_command(args, &rv)) rv = execute(args); } return rv; }
/* builtin.c * contans the switch and the functions for built in commands */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "smsh.h" #include "varlib.h" int assign(char *); int okname(char *); int builtin_command(char **args, int *resultp) /* * purpose: run a builtin command * returns: 1 if args[0] is builtin, 0 if not * details: test args[0] against all know built-ins. Call functions */ { int rv = 0; if (strcmp(args[0], "set") == 0){ VLlist(); *resultp = 0; rv = 1; }else if(strchr(args[0], '=') != NULL){ *resultp = assign(args[0]); if (*resultp != -1) rv = 1; }else if (strcmp(args[0], "export") == 0){ if (args[1] != NULL && okname(args[1])) *resultp = VLexport(args[1]); else *resultp = 1; rv = 1; }else if (strcmp(args[0], "unset") == 0){ VLfree(); rv = 1; } return rv; } int assign(char *str) /* * purpose: execute name=val AND ensure that name is legal * returns: -1 for illegal lval, or result of VLstore * warning: modifies the string, but stores it to normal */ { char *cp; int rv; cp = strchr(str, '='); *cp = '\0'; rv = (okname(str) ? VLstore(str, cp+1): -1); *cp = '='; return rv; } int okname(char *str) /* * purpose: datermins if a string is a legal variable name * returns: 0 for no, 1 for yes */ { char *cp; for (cp=str; *cp; cp++){ if ((isdigit(*cp) && cp == str) || !(isalnum(*cp) || *cp == '_')) return 0; } int rv = (cp != str); /* no empty strings, either */ return rv; }
话说书中并没有提到 varlib.h
和 varlib.c
两个文件的源码, 所以我自己补了下面了个文
件.
varlib.h
#ifndef _VARLIB_H #define _VARLIB_H /* varlib.h */ #include <stdio.h> struct var { char *name; char *val; int global; }; void VLlist(); int VLexport(char *); int VLstore(char *, char *); struct var *VLfind(char *); void VLfree(); #endif
varlib.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "smsh.h" #include "varlib.h" static struct var *VLBuf[BUFSIZ]; static int VLindex = 0; int VLstore(char *name, char *val) { if (VLindex >= BUFSIZ){ return 0; } struct var *tmp; char *tn, *tv; tn = emalloc((strlen(name)+1) * sizeof(char)); tv = emalloc((strlen(val) + 1) * sizeof(char)); tn = strcpy(tn, name); tv = strcpy(tv, val); if ((tmp = VLfind(tn)) == NULL){ tmp = emalloc(sizeof(struct var)); tmp->name = tn; tmp->val = tv; tmp->global = 0; VLBuf[VLindex] = tmp; VLindex++; }else{ tmp->val = tv; } return 0; } int VLexport(char *name) { struct var *tmp; if ((tmp = VLfind(name)) == NULL){ return 0; }else{ tmp->global = 1; return 1; } } void VLlist() { int i; for (i = 0; i < VLindex; i++){ printf("%s=%s\n", VLBuf[i]->name, VLBuf[i]->val); } } struct var *VLfind(char *name) { int i; for (i = 0; i < VLindex; i++){ if (strcmp(VLBuf[i]->name, name) == 0){ return VLBuf[i]; } } return NULL; } void VLfree() { int i; for (i = 0; i < VLindex; i++){ free(VLBuf[i]->name); free(VLBuf[i]->val); free(VLBuf[i]); } VLindex = 0; }
编译:
cc smsh2.c controlflow.c builtin.c splitline.c execute.c process.c varlib.c -o smsh3